import json
import re
import logging
logger=logging.getLogger('django')

from django.contrib.auth import login, authenticate, logout
from django.http import JsonResponse
from django.shortcuts import render

from django import http
from django.views import View
from django_redis import get_redis_connection

from celery_tasks.email.tasks import send_verify_email
from meiduo_malll.utils.view import LoginRequiredMixin
from users.models import User


class UsernameCountView(View):
    """判断用户名是否重复注册"""

    def get(self, request, username):
        '''判断用户名是否重复'''
        # 1.查询username在数据库中的个数
        try:
            count = User.objects.filter(username=username).count()
        except Exception as e:
            return JsonResponse({'code': 400,
                                 'errmsg': '访问数据库失败'})

        # 2.返回结果(json) ---> code & errmsg & count
        return JsonResponse({'code': 0,
                             'errmsg': 'ok',
                             'count': count})


class MobileCountView(View):
    def get(self, request, mobile):
        try:
            count = User.objects.filter(mobile=mobile).count()
        except Exception as e:
            return JsonResponse({
                'code': 400,
                'errmsg': '电话号码重复'
            })
        return JsonResponse({
            'code': 0,
            'errmsg': 'ok',
            'count': count
        })


class RegisterView(View):
    def post(self, request):
        '''接收参数, 保存到数据库'''
        # 1.接收参数
        dict = json.loads(request.body.decode())
        username = dict.get('username')
        password = dict.get('password')
        password2 = dict.get('password2')
        mobile = dict.get('mobile')
        allow = dict.get('allow')
        sms_code_client = dict.get('sms_code')

        # 2.校验(整体)
        if not all([username, password, password2, mobile, allow, sms_code_client]):
            return http.JsonResponse({'code': 400,
                                      'errmsg': '缺少必传参数'})

        # 3.username检验
        if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username):
            return http.JsonResponse({'code': 400,
                                      'errmsg': 'username格式有误'})

        # 4.password检验
        if not re.match(r'^[a-zA-Z0-9]{8,20}$', password):
            return http.JsonResponse({'code': 400,
                                      'errmsg': 'password格式有误'})

        # 5.password2 和 password
        if password != password2:
            return http.JsonResponse({'code': 400,
                                      'errmsg': '两次输入不对'})
        # 6.mobile检验
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.JsonResponse({'code': 400,
                                      'errmsg': 'mobile格式有误'})
        # 7.allow检验
        if allow != True:
            return http.JsonResponse({'code': 400,
                                      'errmsg': 'allow格式有误'})

        # 8.sms_code检验 (链接redis数据库)
        redis_conn = get_redis_connection('verify_code')

        # 9.从redis中取值
        sms_code_server = redis_conn.get(mobile)

        # 10.判断该值是否存在
        if not sms_code_server:
            return http.JsonResponse({'code': 400,
                                      'errmsg': '短信验证码过期'})
        # 11.把redis中取得值和前端发的值对比
        if sms_code_client != sms_code_server.decode():
            return http.JsonResponse({'code': 400,
                                      'errmsg': '验证码有误'})

        # 12.保存到数据库 (username password mobile)
        try:
            user = User.objects.create_user(username=username,
                                            password=password,
                                            mobile=mobile)
        except Exception as e:
            return http.JsonResponse({'code': 400,
                                      'errmsg': '保存到数据库出错'})

        login(request, user)

        # 13.拼接json返回
        response = JsonResponse({'code': 0,
                                 'errmsg': 'ok'})
        response.set_cookie('username',
                            user.username,
                            max_age=3600 * 24 * 14)
        return response


class LoginView(View):

    def post(self, request):
        '''实现登录接口'''
        # 1.接收参数
        dict = json.loads(request.body.decode())
        username = dict.get('username')
        password = dict.get('password')
        remembered = dict.get('remembered')

        # 2.校验(整体 + 单个)
        if not all([username, password]):
            return JsonResponse({'code': 400,
                                 'errmsg': '缺少必传参数'})

        # 3.验证是否能够登录
        user = authenticate(username=username,
                            password=password)

        # 判断是否为空,如果为空,返回
        if user is None:
            return JsonResponse({'code': 400,
                                 'errmsg': '用户名或者密码错误'})

        # 4.状态保持
        login(request, user)

        # 5.判断是否记住用户
        if remembered != True:
            # 7.如果没有记住: 关闭立刻失效
            request.session.set_expiry(0)
        else:
            # 6.如果记住:  设置为两周有效
            request.session.set_expiry(None)

        # 8.返回json
        response = JsonResponse({'code': 0,
                                 'errmsg': 'ok'})
        response.set_cookie('username',
                            user.username,
                            max_age=3600 * 24 * 14)
        return response


class LogoutView(View):
    def delete(self, request):
        """实现退出登录逻辑"""

        # 清理 session
        logout(request)

        # 创建 response 对象.
        response = JsonResponse({'code': 0,
                                 'errmsg': 'ok'})

        # 调用对象的 delete_cookie 方法, 清除cookie
        response.delete_cookie('username')

        # 返回响应
        return response

class UserInfoView(LoginRequiredMixin,View):
    """用户中心"""

    def get(self, request):
        info_data={
            'username':request.user.username,
            'mobile':request.user.mobile,
            'email':request.user.email,
            'email_active':request.user.email_active
        }
        return JsonResponse({'code': 0,
                             'errmsg': 'ok',
                             'info_data':info_data})

class EmailView(View):
    def put(self,request):
        dict=json.loads(request.body.decode())
        email=dict.get('email')
        if not email:
            return JsonResponse({'code':400,
                                 'errmsg':'缺少参数email'})
        if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
            return JsonResponse({'code':400,
                                 'errmsg':'email格式不对'})
        try:
            request.user.email=email
            request.user.save()
        except Exception as e:
            # logger(e)
            return JsonResponse({'code':400,
                                 'errmsg':'邮箱保存到数据库失败'})
        email='<'+email+'>'

        verify_url=request.user.generate_verify_email_url()
        send_verify_email.delay(email,verify_url)

        return JsonResponse({
            'code':0,
            'errmsg':'邮箱添加成功'
        })

class EmailActiveView(View):
    def put(self,request):
        token=request.GET.get('token')
        if not token:
            return JsonResponse({'code':400,
                                 'errmsg':'token参数为空'})
        user=User.check_verify_email_token(token)

        if not user:
            return JsonResponse({'code': 400,
                                 'errmsg': '无效的token'})

            # 修改 email_active 的值为 True
        try:
            user.email_active = True
            user.save()
        except Exception as e:
            return JsonResponse({'code': 400,
                                 'errmsg': '激活邮件失败'})

            # 返回邮箱验证结果
        return JsonResponse({'code': 0,
                             'errmsg': 'ok'})